package vip.mtdp.cloud.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import vip.mtdp.common.HttpStatusEnum;
import vip.mtdp.common.exception.AppRTException;
import vip.mtdp.common.response.CommonResponse;

import javax.servlet.http.HttpServletRequest;

/**
 * @author wangguoqing
 * @since 2020/5/5 16:44
 **/
@Slf4j
@RestController
@RestControllerAdvice
public class AppBaseAdviceController implements ResponseBodyAdvice {


    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        if(o instanceof CommonResponse){
            return o;
        }
        return builderCommonResponse(String.valueOf(HttpStatus.OK.value()),HttpStatus.OK.getReasonPhrase(),o);
    }

    /**
     * 异常处理
     * @param ex
     * @param request
     * @return
     */
    @ExceptionHandler(Exception.class)
    public CommonResponse defaultExceptionHandler(Exception ex, HttpServletRequest request){
        log.info("=====> ex handler = {}",ex);
        //默认 返回 500
        CommonResponse commonResponse = new CommonResponse(String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value()),HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase());
        //app 业务异常,code,message 原样返回
        if(ex instanceof AppRTException){
            AppRTException appEx = (AppRTException) ex;
            commonResponse.setCode(appEx.getCode());
            commonResponse.setMessage(appEx.getMessage());
        }
        //not found 404
        if(ex instanceof NoHandlerFoundException){
            commonResponse = builderCommonResponse(String.valueOf(HttpStatus.NOT_FOUND.value()),HttpStatus.NOT_FOUND.getReasonPhrase());
        }
        return commonResponse;
    }

    /**
     * 参数校验异常
     * @param ex
     * @param request
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public CommonResponse paramExceptionHandler(MethodArgumentNotValidException ex, HttpServletRequest request){
        log.info("=====> ex handler = {}",ex);
        for (FieldError fieldError : ex.getBindingResult().getFieldErrors()){
            //国际化时,可以将message作为code,从配置中心或者其他地方获取具体提示文案
            String message = fieldError.getDefaultMessage();
            return builderCommonResponse(String.valueOf(HttpStatusEnum.ILLEGAL_PARAMETER.getCode()),message,"");
        }
        return builderCommonResponse(String.valueOf(HttpStatusEnum.ILLEGAL_PARAMETER.getCode()),HttpStatusEnum.ILLEGAL_PARAMETER.getExplain(),"");
    }

    /**
     * 组装返回对象
     * @param code
     * @param message
     * @param data
     * @return
     */
    private CommonResponse builderCommonResponse(String code, String message, Object data){
        CommonResponse commonResponse = new CommonResponse(code,message,data);
        return commonResponse;
    }

    /**
     * 组装返回对象
     * @param code
     * @param message
     * @return
     */
    private CommonResponse builderCommonResponse(String code, String message){
        CommonResponse commonResponse = new CommonResponse(code,message);
        return commonResponse;
    }
}
